import {
  CircleRipple,
  CircleSpiral,
  CircleDiffuse,
  CircleLineScan,
} from "./CircleEffect";
import { WallTrail } from "./WallEffect";

/**
 * 通过name查找删除对应的entity
 * @param {*} name entity的name
 * @param {*} _map
 */
function removeEntityByName(name, _map) {
  const viewer = _map || window.component.viewer;
  const entitys = viewer.entities._entities._array;
  for (let i = 0; i < entitys.length; i++) {
    if (entitys[i]._name === name) {
      viewer.entities.remove(entitys[i]);
      i--;
    }
  }
}

/**
 * 删除所有的entity
 * @param {*} name entity的name
 * @param {*} _map
 */
function removeAllEntity(name, _map) {
  const viewer = _map || window.component.viewer;
  const entitys = viewer.entities._entities._array;
  for (let i = 0; i < entitys.length; i++) {
    viewer.entities.remove(entitys[i]);
    i--;
  }
}

function addPointFeatureSymbol(
  geoJson,
  billboardOptions = [],
  labelOptions = {},
  _map
) {
  const viewer = _map || window.component.viewer;

  const pointArr = geoJson.features;
  for (var i = 0; i < pointArr.length; i++) {
    const properties = { ...pointArr[i].properties };
    let imagePath = "./static/images/default.png";
    let imageName = "自定义图标";
    let scale = 0.6;
    let labelShow = false;
    let billboardShow = true;
    let labelText = "";
    let showBackground = true;
    let offset = { x: 0, y: 0 };
    let labelOffset = { x: 10, y: -11 };
    let heightView;
    if (labelOptions.icon) {
      imagePath = labelOptions.icon;
    }

    if (labelOptions.name) {
      imageName = labelOptions.name;
    }

    if (labelOptions.scale !== undefined) {
      scale = labelOptions.scale;
    }

    if (labelOptions.billboard !== undefined) {
      billboardShow = labelOptions.billboard;
    }

    if (labelOptions.showBackground !== undefined) {
      showBackground = labelOptions.showBackground;
    }

    if (labelOptions.label !== undefined) {
      labelShow = labelOptions.label;
      labelText = properties[labelOptions.key];
    }

    if (labelOptions.offset !== undefined) {
      offset = labelOptions.offset;
    }

    if (labelOptions.labelOffset !== undefined) {
      labelOffset = labelOptions.labelOffset;
    }

    if (billboardOptions.length) {
      for (let j = 0; j < billboardOptions.length; j++) {
        const option = billboardOptions[j];
        if (option[pointArr[i].properties[option.key]]) {
          imagePath = option[pointArr[i].properties[option.key]].icon;
          imageName = option[pointArr[i].properties[option.key]].name;
          scale = option[pointArr[i].properties[option.key]].scale || 0.6;
          break;
        }
      }
    }

    if (labelOptions.displayHeight !== undefined) {
      heightView = labelOptions.displayHeight;
    } else {
      heightView = [0.0, Number.MAX_VALUE];
    }
    viewer.entities.add({
      name: imageName,
      properties: properties,
      position: Cesium.Cartesian3.fromDegrees(
        pointArr[i].geometry.coordinates[0],
        pointArr[i].geometry.coordinates[1]
      ),
      billboard: {
        show: billboardShow,
        image: imagePath,
        scale: scale,
        pixelOffset: new Cesium.Cartesian2(offset.x, offset.y),
        heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
        disableDepthTestDistance: Number.POSITIVE_INFINITY,
        eyeOffset: new Cesium.Cartesian3(0, 0, 1),
        distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
          heightView[0],
          heightView[1]
        ),
        zIndex: 1,
      },
      label: {
        // 文字标签
        show: labelShow,
        text: labelText + "",
        font: "500 20px Helvetica", // 15pt monospace
        scale: 0.5,
        style: Cesium.LabelStyle.FILL,
        outlineColor: Cesium.Color.WHITE,
        outlineWidth: 1,
        fillColor: Cesium.Color.WHITE,
        pixelOffset: new Cesium.Cartesian2(
          offset.x + labelOffset.x,
          offset.y + labelOffset.y
        ), // 偏移量
        showBackground: true,
        backgroundColor: showBackground
          ? new Cesium.Color(0.5, 0.6, 1, 1.0)
          : new Cesium.Color(0, 0, 0, 0.75),
        heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
        disableDepthTestDistance: Number.POSITIVE_INFINITY,
        eyeOffset: new Cesium.Cartesian3(0, 0, -10),
        distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
          heightView[0],
          heightView[1]
        ),
        zIndex: 2,
      },
    });
  }
}

function addText(Position, options, _map) {
  // var Position = Cesium.Cartesian3.fromDegrees(long, lat, height);

  var viewer = _map || window.component.viewer;

  viewer.entities.add({
    name: options.name || "text",
    position: Position,
    label: {
      show: true,
      text: options.text + "",
      font: "500 20px Helvetica", // 15pt monospace
      scale: 1,
      style: Cesium.LabelStyle.FILL,
      outlineColor: options.outlineColor || Cesium.Color.WHITE,
      outlineWidth: 1,
      fillColor: options.fillColor || Cesium.Color.ORANGE,
      horizontalOrigin: Cesium.HorizontalOrigin.CENTER, //对齐方式
      verticalOrigin: Cesium.VerticalOrigin.CENTER,
      heightReference: Cesium.HeightReference.RELATIVE_TO_3D_TILE,
      pixelOffset: new Cesium.Cartesian2(20, 0),
      showBackground: options.showBackground,
      backgroundColor:
        options.backgroundColor || Cesium.Color.GOLD.withAlpha(0.5),
    },
  });
}

function addTextCanvas(long, lat, height, options, _map) {
  var viewer = _map || window.component.viewer;

  const canvas = document.createElement("canvas");
  canvas.width = options.canvasWidth || 80;
  canvas.height = options.canvasHeight || 20;
  const context = canvas.getContext("2d");

  context.fillStyle = options.fillStyle || "#000";
  context.font = options.font || "16px sans-serif";
  context.textAlign = options.textAlign || "center";
  context.textBaseline = options.textBaseline || "middle";
  context.fillText(options.text, canvas.width / 2, canvas.height / 2);

  const image = new Image();
  image.src = canvas.toDataURL();

  viewer.entities.add({
    name: options.name || "textCanvas",
    rectangle: {
      coordinates: Cesium.Rectangle.fromDegrees(
        long - 0.000015,
        lat - 0.0000075,
        long + 0.000015,
        lat + 0.0000075
      ),
      //coordinates: new Cesium.BoundingRectangle(0,0,100,100),
      material: new Cesium.ImageMaterialProperty({
        image: image,
        transparent: true,
      }),
    },
  });
}

function addBillboard(long, lat, height, options, _map) {
  var Position = Cesium.Cartesian3.fromDegrees(long, lat, height);

  var viewer = _map || window.component.viewer;
  viewer.entities.add({
    name: options.name,
    position: Position,
    // 图标
    billboard: {
      image: options.image,
      width: 50,
      height: 50,
      // sizeInMeters: true,
    },
    label: {
      //文字标签
      text: options.text,
      font: "20px sans-serif",
      style: Cesium.LabelStyle.FILL,
      // 对齐方式(水平和竖直)
      horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
      verticalOrigin: Cesium.VerticalOrigin.CENTER,
      pixelOffset: options.pixelOffset || new Cesium.Cartesian2(0, 0),
      showBackground: true,
      backgroundColor: Cesium.Color.fromBytes(0, 70, 24),
      sizeInMeters: true,
      heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
      disableDepthTestDistance: Number.POSITIVE_INFINITY,
    },
  });
}

async function addBillboardCanvas(long, lat, height, options, _map) {
  var viewer = _map || window.component.viewer;

  let image = await canvasImage(options);

  // 绘制billboard
  viewer.entities.add({
    name: options.name || "billboardCanvas",
    position: Cesium.Cartesian3.fromDegrees(long, lat, height),
    billboard: {
      image: image,
      scale: options.scale || 1,
      pixelOffset: options.pixelOffset || new Cesium.Cartesian2(0, 0), //偏移量
      horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
      verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
      scaleByDistance: new Cesium.NearFarScalar(2000, 0.6, 12000, 0.2),
      distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 10000),
    },
  });
}

function canvasImage(options) {
  const canvas = document.createElement("canvas");
  const context = canvas.getContext("2d");

  var discountText = options.text || "测试文字";
  var boxHeight = 40;
  var boxWidth = context.measureText(discountText).width * 1.7;

  canvas.width = boxWidth;
  canvas.height = boxHeight;

  context.rect(0, 0, boxWidth, boxHeight);

  return new Promise((resolve) => {
    let bgImg = new Image();
    bgImg.src = options.image || "./static/images/textbg.png"; // 背景图的url
    bgImg.crossOrigin = "Anonymous";
    bgImg.onload = () => {
      context.drawImage(bgImg, 0, 0, boxWidth, boxHeight);
      context.lineWidth = 1; //线宽
      context.strokeStyle = "black"; //描边颜色
      context.font = "15px 宋体";
      context.fillStyle = "#fff"; //文本填充颜色
      context.textBaseline = "middle"; //文本与fillText定义的纵坐标
      context.textAlign = "center"; //文本居中(以fillText定义的横坐标)
      context.fillText(options.text, boxWidth / 2, boxHeight / 2); //文字填充

      const image = new Image();
      image.src = canvas.toDataURL();

      resolve(image);
    };
  });
}

function addPoint(long, lat, height, options, _map) {
  var Position = Cesium.Cartesian3.fromDegrees(long, lat, height);

  var viewer = _map || window.component.viewer;
  let entity = new Cesium.Entity({
    name: options.name || "point",
    show: true,
    position: Position,
    point: {
      show: true,
      pixelSize: options.pixelSize || 4,
      heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
      color: options.color || Cesium.Color.RED,
      outlineColor: options.outlineColor || Cesium.Color.YELLOW,
      outlineWidth: 2,
      disableDepthTestDistance: Number.POSITIVE_INFINITY,
      distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 20000),
    },
  });
  viewer.entities.add(entity);
}

/**
 * 添加区
 * @param {*} dotsArr 二维坐标点数组，包含挖空区域数组
 * @param {*} name 实体名称
 * @param {*} material 填充材质，可以为颜色
 * @param {*} outlineWidth 边框线宽度
 * @param {*} outlineColor 边框线颜色
 * @param {*} _map 地图对象
 */
function addPolygon(dotsArr, options, _map) {
  const map3D = _map || window.component.viewer;
  let positions = null;
  const holes = [];
  dotsArr.map((item, i) => {
    addPolyline(item, { name: options.name || "polygon" }, _map);
    const itemPositions = item
      .join(",")
      .split(",")
      .map((ele) => {
        return ele;
      });
    if (i === 0) {
      positions = Cesium.Cartesian3.fromDegreesArray(itemPositions);
    } else {
      const hole = Cesium.Cartesian3.fromDegreesArray(itemPositions);
      holes.push({ positions: hole });
    }
  });
  const hierarchy = {
    positions,
    // 由于挖的这个洞,是x本身的一种数组集合,所以每一个对象里,又是一个x的形式
    holes,
  };
  const polygon = {
    name: options.name || "polygon",
    polygon: {
      // 坐标点
      hierarchy,
      // 是否指定各点高度
      perPositionHeight: false,
      height: options.height || 0,
      extrudedHeight: options.extrudedHeight || 0,
      material:
        options.material ||
        new Cesium.Color(255 / 255, 48 / 255, 64 / 255, 0.5),
      fill: options.fill || true,
      // 轮廓线颜色
      outlineColor:
        options.outlineColor ||
        new Cesium.Color(253 / 255, 255 / 255, 59 / 255, 1),
      outlineWidth: options.outlineWidth || 1.0,
      // 轮廓线是否显示
      outline: true,
      // 根据高度控制显示隐藏
      distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
        0.0,
        1400000
      ),
    },
  };
  map3D.entities.add(polygon);
}
/**
 * 添加线
 * @param {*} dotsArr 二维坐标点数组
 * @param {*} name 实体名称
 * @param {*} material 填充材质，可以为颜色
 * @param {*} width 线宽
 * @param {*} _map 地图对象
 */
function addPolyline(dotsArr, options, _map) {
  const positions = dotsArr
    .join(",")
    .split(",")
    .map((ele) => {
      return ele;
    });
  const map3D = _map || window.component.viewer;
  const polyline = {
    name: options.name || "polyline",
    polyline: {
      positions: Cesium.Cartesian3.fromDegreesArray(positions),
      width: options.width || 4,
      clampToGround: true,
      material:
        options.material ||
        new Cesium.PolylineGlowMaterialProperty({
          glowPower: 0.3,
          color: new Cesium.Color(253 / 255, 255 / 255, 59 / 255, 1),
        }),
    },
  };
  map3D.entities.add(polyline);
}

/**
 * 添加选中状态的图标标注
 * @param {*} x 添加位置的精度
 * @param {*} y 添加位置的纬度
 * @param {*} options 添加的属性
 * @param {*} _map
 */
function addSelectedSymbol(x, y, options, _map) {
  const viewer = _map || window.component.viewer;
  let imagePath = "./static/images/default.png";
  if (options.image) {
    imagePath = options.image;
  }

  // 跳动最大高度
  const maxHeight = 30;
  // 跳动速率
  const step = 2;
  // 过程高度
  let height = 0;
  // 跳动反转标记
  let statusForBounce = true;

  viewer.entities.add({
    name: "defaultSelect",
    position: new Cesium.CallbackProperty(function () {
      if (statusForBounce) {
        height = height - step;
        if (height <= 0) {
          statusForBounce = false;
        }
      } else {
        height = height + step;
        if (height >= maxHeight) {
          statusForBounce = true;
        }
      }

      return Cesium.Cartesian3.fromDegrees(x, y, height);
    }, false),
    billboard: {
      image: imagePath,
      scale: 0.7,
      disableDepthTestDistance: Number.POSITIVE_INFINITY,
    },
  });
}

function addGeoJsonEntity(url, options, _map) {
  const map3D = _map || window.component.viewer;
  const dataSourcePromise = new Cesium.GeoJsonDataSource.load(url);

  dataSourcePromise.then(function (dataSource) {
    map3D.dataSources.add(dataSource).then(() => {
      let alpha = 0.7;
      const clampToGround = true;

      if (options.alpha) {
        alpha = options.alpha;
      }

      const entities = dataSource.entities._entities._array;

      if (entities.length > 0) {
        for (let i = 0; i < entities.length; i++) {
          const entity = entities[i];
          console.log("entity", entity, options);
          if (!options.type) continue;
          if (options.type === "Polygon") {
            entity.polygon.height = undefined;

            entity.polygon.outlineWidth = 1;

            if (options.fillPolygon) {
              let pc;
              if (typeof options.fillColor === "object") {
                pc = new Cesium.Color.fromCssColorString(
                  options.fillColor[
                    entity.properties[options.propertyKey]._value
                  ]
                ).withAlpha(alpha);
              } else {
                pc = new Cesium.Color.fromCssColorString(
                  options.fillColor
                ).withAlpha(alpha);
              }

              entity.polygon.material = pc;
            } else {
              entity.polygon.outline = false;
              entity.polygon.fill = false;
              entity.polygon.show = false;
            }

            if (clampToGround) {
              entity.polygon.clampToGround = clampToGround;
              entity.polygon.classificationType =
                Cesium.ClassificationType.BOTH;
            }

            if (options.polyLine) {
              // 根据配置获取颜色
              let polylineColor = "#ffffff";
              if (typeof options.polylineColor === "object") {
                polylineColor =
                  options.polylineColor[
                    entity.properties[options.propertyKey]._value
                  ];
              } else if (typeof options.polylineColor === "string") {
                polylineColor = options.polylineColor;
              }

              // 设置outline颜色
              entity.polygon.outlineColor = new Cesium.Color.fromCssColorString(
                polylineColor
              ).withAlpha(0);
              const outlineEntity = new Cesium.Entity({
                name: options.key,
                polyline: {
                  width: options.polylineWidth ? options.polylineWidth : 2,
                  height: options.height ? options.height : 0,
                  positions: entity.polygon.hierarchy._value.positions,
                  material: new Cesium.Color.fromCssColorString(polylineColor),
                  clampToGround: true,
                },
              });

              map3D.entities.add(outlineEntity);
            }
          }
          if (options.type === "Point") {
            let labelImage = "point";

            entity.height = 430;

            if (options.icon) {
              labelImage = options.icon;
            }

            entity._billboard._image._value =
              "./static/images/" + labelImage + ".png";
            // entity._width = 20;
            entity.billboard.disableDepthTestDistance =
              Number.POSITIVE_INFINITY;
          }
          if (options.type === "LineString") {
            let polylineColor = "#50a955";
            let polylineWidth = 5;
            if (options.polylineColor) {
              polylineColor = options.polylineColor;
            }
            if (options.polylineWidth) {
              polylineWidth = options.polylineWidth;
            }
            const pc = new Cesium.Color.fromCssColorString(
              polylineColor
            ).withAlpha(alpha);
            entity.polyline = {
              positions: entity.polygon.hierarchy._value.positions,
              width: polylineWidth,
              material: pc,
              clampToGround: true,
            };

            entity.polygon.show = false;
          }
          if (options.type === "Wall") {
            entity.wall.material = new Cesium.ImageMaterialProperty({
              transparent: true, // 设置透明
              image: "./static/images/wall.png",
              repeat: new Cesium.Cartesian2(1.0, 1),
              // color: Cesium.Color.RED,
            });
            entity.wall.minimumHeights = [500, 500];
            entity.wall.clampToGround = true;
            entity.polygon.show = false;
          }
        }
      }
    });
    dataSource.name = options.key;
  });
}

function removeGeoJsonEntity(vueKey, _map) {
  const viewer = _map;
  viewer.dataSources.remove(viewer.dataSources.getByName(vueKey)[0]);
}

function registerLeftClick(handerFunction) {
  // cesium点击事件
  this.handler = new this.Cesium.ScreenSpaceEventHandler(
    this.viewer.scene.canvas
  );
  const mouseOverHandler =
    handerFunction ||
    function (movement) {
      const position = movement.position || movement.endPosition;
      const cartesian = self.viewer.getCartesian3Position(position);

      const cartographic2 = Cesium.Cartographic.fromCartesian(cartesian);
      const longitude = Cesium.Math.toDegrees(cartographic2.longitude);
      const latitude = Cesium.Math.toDegrees(cartographic2.latitude);
      const height = cartographic2.height;

      console.log(longitude, latitude, height);
    };
  this.handler.setInputAction(
    mouseOverHandler,
    this.Cesium.ScreenSpaceEventType.LEFT_CLICK
  );
}

function removeLeftClick() {
  if (this.handler) {
    this.handler.removeInputAction(this.Cesium.ScreenSpaceEventType.LEFT_CLICK);
    this.handler = null;
  }
}

export default {
  addText,
  addTextCanvas,
  addBillboard,
  addBillboardCanvas,
  addPoint,
  addPolyline,
  addPolygon,
  removeEntityByName,
  removeAllEntity,
  addPointFeatureSymbol,
  addSelectedSymbol,
  addGeoJsonEntity,
  removeGeoJsonEntity,
  registerLeftClick,
  removeLeftClick,
  WallTrail,
  CircleRipple,
  CircleSpiral,
  CircleDiffuse,
  CircleLineScan,
};
